# -*- coding: utf-8 -*-
from utils.config import *
from utils.utils import *
import pandas as pd
import utils.MyTT as Mytt
# import logging
from utils.log import Loggers
from utils.pushService import PushService
import numpy as np

logger = Loggers('LianDieSignal')
# logger.clear()

pushSer = PushService('连续上涨/下跌反转信号')


def calculate_bottom_rebound_signals(df,kNumber=10,kDiezhang=5):
    """
    优化后的触底反弹信号计算
    参数:
        df: DataFrame, 包含OHLCV数据
    返回:
        添加了信号列的DataFrame
    """
    # 确保有必要的列
    if not all(col in df.columns for col in ['open', 'high', 'low', 'close', 'volume']):
        raise ValueError("DataFrame必须包含open, high, low, close, volume列")
    
    df = df[df.index < '2025-5-21 5:0:0']

    # 计算技术指标
    df['ma5'] = Mytt.MA(df['close'], 5)
    df['ema5'] = Mytt.EMA(df['close'],5)
    
    # 初始化信号列
    df['signal'] = 0
    
    # 寻找 N周期内 最高价
    df['high_max'] =Mytt.HHV(df['close'],kNumber*3)
    # 最高价距离今天的天数
    df['high_day'] = Mytt.BARSLAST(df['close'] == df['high_max'])
    # 最高价距离今天的跌幅
    df['high_diezhang'] = (df['high_max'] - df['close'])/df['close']
    # 标记连续下跌时间天数
    df['ma5_yazhi'] = Mytt.BARSLAST( (df['close'] < df['close'].shift(2)) & (df['high_max'] == df['high_max'].shift(1)) )
    # 被压制的天数数量 需要大于90%
    df['ma5_yazhi_radio'] = df['ma5_yazhi'] / df['high_day']

    df.loc[( df['ma5_yazhi_radio']>0.8 ) ,'signal_befor'] = 1
    # print((df[df['signal_befor']==1]).tail())
    print((df).tail(30))
    exit()
    # 使用向量化操作计算累计跌幅和持续时间
    consecutive_below_ma5 = below_ma5.astype(int).groupby((~below_ma5).cumsum()).cumsum()
    
    # 找到下跌开始的索引
    start_indices = np.where((~below_ma5.shift(1)) & below_ma5)[0]
    
    # 计算累计跌幅和持续时间
    for start in start_indices:
        end = start + consecutive_below_ma5[start:]
        mask = (np.arange(len(df)) >= start) & (np.arange(len(df)) < start + consecutive_below_ma5[start:])
        df.loc[mask, 'accumulated_drop'] = (df['close'].iloc[start] - df['close'].iloc[mask]) / df['close'].iloc[start] * 100
        df.loc[mask, 'drop_duration'] = np.arange(1, len(mask) + 1)
    
    # 检查做多信号条件
    long_condition = (
        (consecutive_below_ma5 >= kNumber) &
        (df['accumulated_drop'] >= kDiezhang) &
        (df['close'] > df['ema5']) &
        (df['close'].shift(1) > df['ema5'].shift(1)) &
        (df['close'].shift(2) > df['ema5'].shift(2)) &
        (df['close'] > df['close'].shift(1)) &
        (df['close'].shift(1) > df['close'].shift(2)) &
        (df['close'].shift(2) > df['close'].shift(3))
    )
    df['long_signal'] = long_condition
    df.loc[long_condition, 'signal'] = 1
    
    # 检查做空信号条件
    short_condition = (
        (consecutive_below_ma5 >= kNumber) &
        (df['accumulated_drop'] >= kDiezhang) &
        (df['close'] < df['ema5']) &
        (df['close'].shift(1) < df['ema5'].shift(1)) &
        (df['close'].shift(2) < df['ema5'].shift(2)) &
        (df['close'] < df['close'].shift(1)) &
        (df['close'].shift(1) < df['close'].shift(2)) &
        (df['close'].shift(2) < df['close'].shift(3))
    )
    df['short_signal'] = short_condition
    df.loc[short_condition, 'signal'] = -1
    
    return df
 

# 循环处理
for instId in config_movingAverage_instId:
    # 读取300条最新的数据
    try:
        df = loadCsvData(instId,'15m')
    except:
        continue

    # 10日均线
    df = calculate_bottom_rebound_signals(df)
    
    # 快速计算信号近期胜率
    # shenglv5,shenglv10 = getShenglv(df)
    # 取出所有满足条件的信号数据
    df_signal = df[df['signal']!=0]
    print(len(df_signal))
    print(df_signal.tail(30))
    exit()
    # 拿到最后出现信号的数据
    after_signal = df_signal.iloc[-1]
    xiaoshu = 1 if after_signal['close']>0 else 3
    # 计算止损点位
    # zhisun= round(after_signal['recent_low'] + (after_signal['atr'] if after_signal['signal'] == -1 else after_signal['atr']*-1),xiaoshu)

    fangxiang = '做多' if after_signal['signal']>0 else '做空'
    signal_text = f"{instId}{fangxiang} 最近信号：{after_signal.name} 收盘价：{after_signal['close']} "

    # 计算止损位置
    # zhisunR = round( abs((zhisun - after_signal['close'])) /after_signal['close'] *100,2)

    # signal_text+= f"止损：{zhisun}({zhisunR}%)"
    hour = getHoursPassed(after_signal.name)
    # 进行日志记录
    if hour < 25:
        # 25小时内的新信号 就可以 进行钉钉推送
        if pushSer.add_push_item(after_signal, instId,[
            f"止损：近高低点，止盈：ema10均线\n\n",
        ]):
            logger.info(signal_text)
    else:
        print(f"过期信号：{signal_text}")
    # 完成消息的通知
pushSer.push_message()

